using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class BCWShadowController : MonoBehaviour
{
	public int step = 15;

	public int cone = 90;

	public LayerMask shadowMask;

	public Material shadowMaterial;

	public Color gizmoColor = Color.yellow;

	public Vector3[] points;

	public float maxYDistance = 2f;

	public float recalculateTime = 0.01f;

	public static GameObject shadowParent;

	public ShadowType shadowType;

	private Vector3 oldPosVector = Vector3.zero;

	private Vector3 delta;

	private ListArray<Vector3> vertexForShadow;

	private ListArray<Vector2> uv;

	private ListArray<int> triangles;

	private bool firstCalculateTri = true;

	[HideInInspector]
	public GameObject carShadow;

	[HideInInspector]
	public GameObject titanShadow;

	[HideInInspector]
	public GameObject motoShadow;

	[HideInInspector]
	public MeshFilter meshFilter;

	[HideInInspector]
	public MeshRenderer meshRenderer;

	private IEnumerator updateMesh;

	private Mesh m;

	private List<int> preTriangles = new List<int>();

	private void OnEnable()
	{
		if (meshFilter != null)
		{
			meshFilter.gameObject.SetActive(true);
		}
	}

	private void OnDisable()
	{
		if ((bool)meshFilter)
		{
			meshFilter.gameObject.SetActive(false);
		}
		StopCoroutine(UpdateMesh());
	}

	private void OnDestroy()
	{
		StopAllCoroutines();
		meshFilter = null;
		meshRenderer = null;
		if (titanShadow != null)
		{
			Object.Destroy(titanShadow);
		}
		if (carShadow != null && PlayerBehavior.MyPlayer != null && PlayerBehavior.MyPlayer.isMine)
		{
			Object.Destroy(carShadow);
		}
		if (motoShadow != null)
		{
			Object.Destroy(motoShadow);
		}
	}

	private void CreateSpecialArray()
	{
		int num = 0;
		num = cone / step * (cone / step);
		vertexForShadow = new ListArray<Vector3>(num);
		uv = new ListArray<Vector2>(num);
	}

	private void Start()
	{
		if (shadowParent == null)
		{
			shadowParent = new GameObject("EntityShadows");
		}
		switch (shadowType)
		{
		case ShadowType.TitanShadow:
			if (titanShadow == null)
			{
				titanShadow = new GameObject("TitanShadow");
				titanShadow.transform.parent = shadowParent.transform;
				meshFilter = titanShadow.AddComponent<MeshFilter>();
				meshRenderer = titanShadow.AddComponent<MeshRenderer>();
				meshRenderer.receiveShadows = false;
				meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
				Material material4 = Resources.Load("Materials/BCWShadowTitan", typeof(Material)) as Material;
				meshRenderer.material = material4;
				meshFilter.mesh.MarkDynamic();
			}
			else if (PlayerBehavior.MyPlayer.isMine)
			{
				meshFilter = titanShadow.GetComponent<MeshFilter>();
				meshRenderer = titanShadow.GetComponent<MeshRenderer>();
				meshFilter.mesh.MarkDynamic();
				titanShadow.SetActive(true);
			}
			else
			{
				titanShadow = new GameObject("TitanShadow");
				titanShadow.transform.parent = shadowParent.transform;
				meshFilter = titanShadow.AddComponent<MeshFilter>();
				meshRenderer = titanShadow.AddComponent<MeshRenderer>();
				meshRenderer.receiveShadows = false;
				meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
				Material material5 = Resources.Load("Materials/BCWShadowTitan", typeof(Material)) as Material;
				meshRenderer.material = material5;
				meshFilter.mesh.MarkDynamic();
			}
			break;
		case ShadowType.CarShadow:
			if (PlayerBehavior.MyPlayer.isMine)
			{
				recalculateTime = 0.01f;
				if (carShadow == null)
				{
					carShadow = new GameObject("CarShadow");
					carShadow.transform.parent = shadowParent.transform;
					meshFilter = carShadow.AddComponent<MeshFilter>();
					meshRenderer = carShadow.AddComponent<MeshRenderer>();
					meshRenderer.receiveShadows = false;
					meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
					Material material3 = Resources.Load("Materials/BCWShadowCar", typeof(Material)) as Material;
					meshRenderer.material = material3;
					meshFilter.mesh.MarkDynamic();
				}
				else
				{
					meshFilter = carShadow.GetComponent<MeshFilter>();
					meshRenderer = carShadow.GetComponent<MeshRenderer>();
					meshFilter.mesh.MarkDynamic();
					carShadow.SetActive(true);
				}
			}
			break;
		case ShadowType.MotoShadow:
			recalculateTime = 0.01f;
			if (motoShadow == null)
			{
				motoShadow = new GameObject("MotoShadow");
				motoShadow.transform.parent = shadowParent.transform;
				meshFilter = motoShadow.AddComponent<MeshFilter>();
				meshRenderer = motoShadow.AddComponent<MeshRenderer>();
				meshRenderer.receiveShadows = false;
				meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
				Material material = Resources.Load("Materials/BCWShadowMoto", typeof(Material)) as Material;
				meshRenderer.material = material;
				meshFilter.mesh.MarkDynamic();
			}
			else if (PlayerBehavior.MyPlayer.isMine)
			{
				meshFilter = motoShadow.GetComponent<MeshFilter>();
				meshRenderer = motoShadow.GetComponent<MeshRenderer>();
				meshFilter.mesh.MarkDynamic();
				motoShadow.SetActive(true);
			}
			else
			{
				motoShadow = new GameObject("MotoShadow");
				motoShadow.transform.parent = shadowParent.transform;
				meshFilter = motoShadow.AddComponent<MeshFilter>();
				meshRenderer = motoShadow.AddComponent<MeshRenderer>();
				meshRenderer.receiveShadows = false;
				meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
				Material material2 = Resources.Load("Materials/BCWShadowMoto", typeof(Material)) as Material;
				meshRenderer.material = material2;
				meshFilter.mesh.MarkDynamic();
			}
			break;
		}
		CreateSpecialArray();
		string[] layerNames = new string[8] { "Default", "Level", "dno", "collidePoint", "boat", "Walls", "FPSWeapon", "Streetlight" };
		shadowMask = shadowMask.AddToMask(layerNames);
		oldPosVector = base.transform.position;
	}

	public void Update()
	{
		delta = base.transform.position - oldPosVector;
		if (delta != Vector3.zero)
		{
			if ((bool)titanShadow)
			{
				titanShadow.transform.position += new Vector3(delta.x, delta.y, delta.z);
			}
			else if ((bool)carShadow && PlayerBehavior.MyPlayer.isMine)
			{
				carShadow.transform.position += new Vector3(delta.x, delta.y, delta.z);
			}
			else if ((bool)motoShadow)
			{
				motoShadow.transform.position += new Vector3(delta.x, delta.y, delta.z);
			}
		}
		oldPosVector = base.transform.position;
	}

	public void TurnOnEntityShadow(bool value)
	{
		if (value)
		{
			base.enabled = value;
			base.gameObject.SetActive(value);
			if (updateMesh != null)
			{
				StopCoroutine(updateMesh);
			}
			updateMesh = UpdateMesh();
			StartCoroutine(updateMesh);
		}
		else
		{
			if (updateMesh != null)
			{
				StopCoroutine(updateMesh);
				updateMesh = null;
			}
			base.enabled = value;
			base.gameObject.SetActive(value);
		}
	}

	private IEnumerator UpdateMesh()
	{
		while (true)
		{
			yield return new WaitForEndOfFrame();
			if ((meshRenderer != null && !meshRenderer.enabled) || cone == 0 || step == 0)
			{
				continue;
			}
			if (cone % 2 != 0)
			{
				cone++;
			}
			if (cone / step < 2)
			{
				step = cone / 2;
			}
			if (cone % step != 0)
			{
				step++;
				continue;
			}
			vertexForShadow.Clear();
			if (shadowType == ShadowType.TitanShadow)
			{
				for (float x2 = -cone / 2; x2 < (float)(cone / 2); x2 += (float)step)
				{
					for (float y2 = -cone / 2; y2 < (float)(cone / 2); y2 += (float)step)
					{
						Vector3 noAngle2 = base.transform.forward;
						Quaternion spreadAngleX2 = Quaternion.AngleAxis(x2, base.transform.up);
						Quaternion spreadAngleY2 = Quaternion.AngleAxis(y2, base.transform.right);
						Ray ray2 = new Ray(direction: spreadAngleX2 * noAngle2 + spreadAngleY2 * noAngle2, origin: base.transform.position);
						RaycastHit hit;
						if (Physics.Raycast(ray2, out hit, maxYDistance * 150f, shadowMask))
						{
							vertexForShadow.Add(hit.point + Vector3.up * 0.1f);
						}
						else
						{
							vertexForShadow.Add(Vector3.zero);
						}
					}
				}
			}
			else
			{
				for (float x = -cone / 2; x < (float)(cone / 2); x += (float)step)
				{
					for (float y = -cone; y < (float)cone; y += (float)(step * 2))
					{
						Vector3 noAngle = base.transform.forward;
						Quaternion spreadAngleX = Quaternion.AngleAxis(x, base.transform.up);
						Quaternion spreadAngleY = Quaternion.AngleAxis(y, base.transform.right);
						Ray ray = new Ray(direction: spreadAngleX * noAngle + spreadAngleY * noAngle, origin: base.transform.position);
						RaycastHit hit2;
						if (Physics.Raycast(ray, out hit2, maxYDistance * 150f, shadowMask))
						{
							vertexForShadow.Add(hit2.point + Vector3.up * 0.1f);
						}
						else
						{
							vertexForShadow.Add(Vector3.zero);
						}
					}
				}
			}
			if ((bool)titanShadow)
			{
				titanShadow.transform.position = Vector3.zero;
			}
			else if ((bool)carShadow)
			{
				carShadow.transform.position = Vector3.zero;
			}
			else if ((bool)motoShadow)
			{
				motoShadow.transform.position = Vector3.zero;
			}
			if (firstCalculateTri)
			{
				CalculateTrianglesSize(vertexForShadow.ToArray());
				continue;
			}
			meshFilter.sharedMesh = CreateMesh(vertexForShadow.ToArray());
			meshFilter.sharedMesh.RecalculateBounds();
			meshFilter.sharedMesh.RecalculateNormals();
			meshRenderer.material.SetVector("_PlayerPosition", new Vector4(base.transform.position.x, base.transform.position.y, base.transform.position.z, 1f));
			if (delta.y * Time.deltaTime > maxYDistance / 4f)
			{
				yield return new WaitForSeconds(recalculateTime / 5f);
			}
			else
			{
				yield return new WaitForSeconds(recalculateTime);
			}
		}
	}

	private Mesh CreateMesh(Vector3[] vertecsCords)
	{
		if (meshFilter.sharedMesh == null)
		{
			m = new Mesh();
		}
		else
		{
			m = meshFilter.sharedMesh;
		}
		m.name = "ScriptedMesh";
		if (vertecsCords.Length < 4)
		{
			return m;
		}
		m.vertices = vertecsCords;
		triangles.Clear();
		uv.Clear();
		int num = cone / step;
		int num2 = num;
		for (int i = 0; i < vertecsCords.Length; i++)
		{
			if (i < vertecsCords.Length - num)
			{
				if ((i + 1) % num != 0 && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num].y) < maxYDistance && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + 1].y) < maxYDistance)
				{
					triangles.Add(i);
					triangles.Add(i + num);
					triangles.Add(i + 1);
				}
				if (i % num != 0 && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num - 1].y) < maxYDistance && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num].y) < maxYDistance)
				{
					triangles.Add(i);
					triangles.Add(i + num - 1);
					triangles.Add(i + num);
				}
			}
		}
		for (int j = 0; j < num; j++)
		{
			for (int k = 0; k < num2; k++)
			{
				uv.Add(new Vector2((float)j / ((float)num - 1f), (float)k / ((float)num2 - 1f)));
			}
		}
		m.uv = uv.ToArray();
		m.triangles = triangles.ToArray();
		return m;
	}

	private void CalculateTrianglesSize(Vector3[] vertecsCords)
	{
		preTriangles.Clear();
		if (vertecsCords.Length < 4)
		{
			return;
		}
		int num = cone / step;
		int num2 = num;
		for (int i = 0; i < vertecsCords.Length; i++)
		{
			if (i < vertecsCords.Length - num)
			{
				if ((i + 1) % num != 0 && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num].y) < maxYDistance && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + 1].y) < maxYDistance)
				{
					preTriangles.Add(i);
					preTriangles.Add(i + num);
					preTriangles.Add(i + 1);
				}
				if (i % num != 0 && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num - 1].y) < maxYDistance && Mathf.Abs(vertecsCords[i].y - vertecsCords[i + num].y) < maxYDistance)
				{
					preTriangles.Add(i);
					preTriangles.Add(i + num - 1);
					preTriangles.Add(i + num);
				}
			}
		}
		triangles = new ListArray<int>(preTriangles.Count);
		firstCalculateTri = false;
	}
}
